package com.schoolvisitors.service;

import com.schoolvisitors.dto.CreateRoomDto;
import com.schoolvisitors.entity.Floor;
import com.schoolvisitors.entity.Room;
import com.schoolvisitors.enums.RoomTypeEnum;
import com.schoolvisitors.exception.BusinessException;
import com.schoolvisitors.repository.FloorRepository;
import com.schoolvisitors.repository.RoomRepository;
import com.schoolvisitors.response.ResultCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class RoomService {
    private final FloorRepository floorRepository;
    private final RoomRepository roomRepository;

    public RoomService(FloorRepository floorRepository, RoomRepository roomRepository) {
        this.floorRepository = floorRepository;
        this.roomRepository = roomRepository;
    }

    public Map<Long, List<Room>> getGroupRoomsByFloorId() {
        // 按照类型和房间号排序
        List<Room> rooms = roomRepository.findAllByDeleteFalse(Sort.by(Sort.Order.asc("subType"), Sort.Order.asc("number")));

        Map<Long, List<Room>> groupedRooms = new LinkedHashMap<>();
        for (Room room : rooms) {
            Long floorId = room.getFloor().getId();
            groupedRooms.computeIfAbsent(floorId, k -> new ArrayList<>()).add(room);
        }
        return groupedRooms;
    }

    @Transactional(rollbackFor = Exception.class)
    public void createRoom(CreateRoomDto dto) {
        // 检查楼层序号是否存在
        Floor floor = floorRepository.findByIdAndDeleteFalse(dto.getFloorId()).orElseThrow(() -> new BusinessException(ResultCode.FLOOR_ID_NOT_FOUND));

        // 校验房号是否重复
        if (roomRepository.existsByNumberAndFloorId(dto.getNumber(), dto.getFloorId())) {
            throw new BusinessException(ResultCode.ROOM_NUMBER_ALREADY_EXISTS);
        }
        Room room = new Room();
        room.setSubType(dto.getSubType());
        room.setNumber(dto.getNumber());
        room.setType(RoomTypeEnum.valueOf(dto.getType()));
        room.setCapacity(dto.getCapacity());
        room.setFloor(floor);
        room.setPointsCost(dto.getPointsCost());
        room.setCubicleCount(dto.getCubicleCount());
        room.setOpenTime(dto.getOpenTime());
        room.setAvailable(dto.getAvailable());
        room.setCloseTime(dto.getCloseTime());
        room.setImg(dto.getImg());
        roomRepository.save(room);

    }

    public List<Room> getRooms(){
        return roomRepository.findAllByDeleteFalse();
    }

    public Room getRoom(Long roomId) {
        if (roomId == null) {
            throw new BusinessException(ResultCode.ROOM_NOT_FOUND);
        }
        return roomRepository.findByIdAndDeleteFalse(roomId).orElseThrow(() -> new BusinessException(ResultCode.ROOM_NOT_FOUND));
    }
    public Room getRoomAndDelete(Long roomId) {
        if (roomId == null) {
            throw new BusinessException(ResultCode.ROOM_NOT_FOUND);
        }
        return roomRepository.findById(roomId).orElseThrow(() -> new BusinessException(ResultCode.ROOM_NOT_FOUND));
    }

    public Page<Room> getRooms(Pageable pageable, Long number) {
        if (number == null) {
            return roomRepository.findAllByDeleteFalse(pageable);
        } else {
            return roomRepository.findAllByNumberAndDeleteFalse(number, pageable);
        }
    }

    public void deleteRoom(Long roomId) {
        Room room = roomRepository.findByIdAndDeleteFalse(roomId).orElseThrow(() -> new BusinessException(ResultCode.ROOM_NOT_FOUND));
        room.setDelete(true);
        roomRepository.save(room);
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateRoom(CreateRoomDto dto) {
        if (dto.getId() == null) {
            throw new BusinessException(ResultCode.ROOM_NOT_FOUND);
        }
        // 获取原始 Room
        Room room = roomRepository.findByIdAndDeleteFalse(dto.getId()).orElseThrow(() -> new BusinessException(ResultCode.ROOM_NOT_FOUND));

        // 校验 cubicleCount 是否被修改
        if (!room.getCubicleCount().equals(dto.getCubicleCount())) {
            throw new BusinessException(ResultCode.CUBICLE_COUNT_CANNOT_BE_MODIFIED);
        }

        // 检查楼层是否存在
        Floor floor = floorRepository.findById(dto.getFloorId())
                .orElseThrow(() -> new BusinessException(ResultCode.FLOOR_ID_NOT_FOUND));

        // 更新除 cubicleCount 外的字段
        room.setSubType(dto.getSubType());
        room.setNumber(dto.getNumber());
        room.setType(RoomTypeEnum.valueOf(dto.getType()));
        room.setCapacity(dto.getCapacity());
        room.setFloor(floor);
        room.setPointsCost(dto.getPointsCost());
        room.setOpenTime(dto.getOpenTime());
        room.setCloseTime(dto.getCloseTime());
        room.setAvailable(dto.getAvailable());
        room.setImg(dto.getImg());
        roomRepository.save(room);
    }

}
